
package com.gitee.jmash.rbac;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import com.crenjoy.proto.mapper.BeanMapper;
import com.crenjoy.proto.mapper.ProtoMapper;
import com.gitee.jmash.common.utils.UUIDUtil;
import com.gitee.jmash.rbac.entity.TokenEntity;
import com.gitee.jmash.rbac.mapper.ResourceMapper;
import com.gitee.jmash.rbac.model.TreeResult;
import jmash.protobuf.TreeList;
import jmash.protobuf.TreeModel;
import jmash.rbac.protobuf.TokenResp;

/**
 * Rbac Mapper.
 *
 * @author <a href="mailto:service@crenjoy.com">crenjoy</a>
 *
 */
@Mapper
public interface RbacMapper extends BeanMapper, ProtoMapper {

  RbacMapper INSTANCE = Mappers.getMapper(RbacMapper.class);

  TokenEntity clone(TokenEntity entity);

  TokenResp model(TokenEntity entity);

  default TreeList treeList(List<TreeResult> list, String excludeId) {
    // 全部资源模型.
    Map<UUID, TreeModel.Builder> map = list.stream()
        .collect(Collectors.toMap(TreeResult::getValue,
            obj -> ResourceMapper.INSTANCE.treeModel(obj).toBuilder(),
            (oldValue, newValue) -> oldValue));
    boolean isroot = false;
    if (StringUtils.isNotBlank(excludeId)) {
      // 去除需要隐藏的资源
      for (TreeResult treeResult : list) {
        if (treeResult.getValue().equals(UUIDUtil.fromString(excludeId))) {
          TreeModel.Builder parent = map.get(treeResult.getParentId());
          if (parent == null) {
            isroot = true;
            break;
          }
        }
      }
      if (!isroot) {
        list = deleteExcludeResource(list, excludeId);
      }
    }
    // 倒序添加孩子
    List<TreeResult> reverseList = new ArrayList<>(list);
    Collections.reverse(reverseList);

    // 数据建立父子关系
    List<UUID> roots = new ArrayList<>();
    for (TreeResult resource : reverseList) {
      TreeModel.Builder model = map.get(resource.getValue());
      TreeModel.Builder parent = map.get(resource.getParentId());
      if (parent == null) {
        roots.add(resource.getValue());
      } else {
        parent.addChildren(0, model);
      }
    }
    if (isroot && StringUtils.isNotBlank(excludeId)) {
      roots.remove(UUIDUtil.fromString(excludeId));
    }
    // 根列表
    TreeList.Builder builder = TreeList.newBuilder();
    for (UUID root : roots) {
      builder.addResults(0, map.get(root));
    }
    return builder.build();
  }

  default List<TreeResult> deleteExcludeResource(List<TreeResult> list, String excludeId) {
    Iterator<TreeResult> iterator = list.iterator();

    while (iterator.hasNext()) {
      TreeResult treeResult = iterator.next();
      if (treeResult.getValue().equals(UUID.fromString(excludeId))) {
        iterator.remove();
      } else if (treeResult.getParentId().equals(UUID.fromString(excludeId))) {
        iterator.remove();
        deleteExcludeResource(list, treeResult.getValue().toString());
      }
    }
    return list;
  }
}
